<?php
/**
 * Created by PhpStorm.
 * User: 65736
 * Date: 2019/2/5 0005
 * Time: 21:54
 */

namespace app\common\widget;


use app\common\library\CatchException;
use think\Config;
use think\Exception;
use think\View;

abstract class WidgetCommon
{
    /**
     * 模板
     * @var string
     */
    var $tpl;

    /**
     * 挂件类型
     * @var string
     */
    var $type;

    /**
     * 属性组
     * @var array
     */
    var $attr = [] ;

    /**
     * Html Dom Attr
     * @var array
     */
    var $domAttrs = [];

    /**
     * 初始化过的模型.
     * @var array
     */
    protected static $initialized = [];

    /**
     * 视图引擎
     * @var View
     */
    protected static $view ;

    /**
     * 构造方法, 渲染挂件
     * @return mixed
     */
    abstract function render();

    /**
     * 构造方法
     * @access public
     * @throws Exception
     */
    public function __construct() {
        // 执行初始化操作
        $this->initialize();
    }

    /**
     * 初始化方法(对象处理)
     * @throws Exception
     */
    protected function initialize() {
        // 初始化静态判断
        $class = get_class($this);
        // 设置挂件类型
        $this->setType($class);
        // 只检测一次
        if (!isset(static::$initialized[$class])) {
            static::$initialized[$class] = true;
            static::init();
            // 检测挂件
            $this->checkWidget();
        }
        // 获取
        $this->tpl = $this->getTpl();
    }

    /**
     * 初始化处理(静态处理)
     * @access protected
     * @return void
     */
    protected static function init()
    {
        // 初始化视图引擎
        self::viewInit();
    }

    /**
     * 初始化视图引擎
     */
     protected static function viewInit() {
        static::$view = new View();
        $view_path = Config::get("widget.view_path");
        $theme = Config::get("widget.theme");
        static::$view->config( "view_path", $view_path.$theme.DS );
        $tplReplaceString = Config::get('template.tpl_replace_string');
        static::$view->assign("tpl_replace_string", $tplReplaceString);
    }

    /**
     * 检测挂件
     * @return bool
     * @throws Exception
     */
    protected function checkWidget(  ) {
        $class = $this->type;
        if ( !class_exists($class) ) {
            $message = "挂件类型不存在[$class]";
            throw new Exception($message, CatchException::WidgetErrorException);
        }
        if ( !is_subclass_of($class, __CLASS__) ) {
            $message = "挂件类不是".__CLASS__."子类";
            throw new Exception($message, CatchException::WidgetErrorException);
        }
        return true;
    }


    /**
     * 设置挂件类型
     * @param string $type 类型值
     * @return $this|static
     */
    private function setType($type) {
        return $this->setField ( "type", $type );
    }

    /**
     * 设置属性值
     * @param string $field 属性字段
     * @param string $value 属性值
     * @return $this|static
     */
    public function setField($field, $value) {
        $this->$field = $value;
        $this->attr [$field] = $value;
        return $this;
    }

    /**
     * 设置Dom属性
     * @param string $attrName  属性名称
     * @param string|array $attrValue 属性值
     * @return $this|static
     */
    public function setDomAttr( $attrName, $attrValue ) {
        $this->domAttrs[$attrName] = $attrValue;
        return $this;
    }

    /**
     * 批量设置DOM属性
     * @param  array $attrList 属性KeyValue列表
     * @return $this
     */
    public function setDomAttrList ( array $attrList ) {
        $this->domAttrs = array_merge( $this->domAttrs, $attrList );
        return $this;
    }

    /**
     * 获取Dom属性值
     * @param $attrName
     * @return mixed|null
     */
    public function getDomAttr( $attrName ) {
        if ( isset($this->domAttrs[$attrName]) ) return $this->domAttrs[$attrName];
        return '';
    }

    /**
     * 移除某个属性
     * @param $attrName
     * @return $this
     */
    public function remDomAttr( $attrName ) {
        if ( isset($this->domAttrs[$attrName]) ) unset($this->domAttrs[$attrName]);
        return $this;
    }

    /**
     * 设置挂件HtmlDomClass值
     * @param array|string $value
     * @return $this
     * @throws Exception
     */
    public function setClass( $value ) {
        if ( !$value ) $this->throwException("挂件HtmlDomClass值非法");
        // 判断是否有class值
        $class = $this->getClass();
        // 判断value数据类型
        $_value = array();
        if ( is_array($value) ) {
            $_value = $value;
        }else{
            $_value [] = $value;
        }
        // 合并原有class值
        $class = array_merge($class, $_value);
        $class = array_unique($class);
        $class = implode(' ', $class);
        $this->setDomAttr('class', $class );
        return $this;
    }

    /**
     * 获取HtmlDomClass值
     * @return array
     */
    public function getClass() {
        $class = $this->getDomAttr('class');
        return $class ? explode(" ", $class) :[];
    }

    /**
     * 移除某个class
     * @param $class
     * @return $this
     */
    public function remClass( $class ) {
        $class_list = $this->getClass();
        $remList = [];
        if ( is_array( $class ) ) {
            $remList = $class;
        }else {
            $remList[] = $class;
        }
        foreach ( $class_list as $k=>$v ) {
            if ( in_array( $v, $remList ) ) unset($class_list[$k]);
        }
        $setClass = '';
        if ( $class_list ) {
            $setClass = implode(' ', array_values($class_list));
        }
        $this->setDomAttr('class', $setClass );
        return $this;
    }

    /**
     * 设置挂件HtmlDomID值
     * @param $value
     * @return $this
     * @throws Exception
     */
    public function setId( $value ) {
        if ( !$value ) $this->throwException("挂件HtmlDomID值非法");
        $this->setDomAttr('id', $value);
        return $this;
    }

    /**
     * 获取挂件HtmlDomID值
     * @return mixed|null
     */
    public function getId() {
        return $this->getDomAttr('id');
    }

    /**
     * 设置placeholder值
     * @param $value
     * @return $this
     * @throws Exception
     */
    public function setPlaceholder( $value ) {
        if ( !$value ) $this->throwException("挂件placeholder值非法");
        $this->setDomAttr( 'placeholder', $value );
        return $this;
    }

    /**
     * 获取placeholder值
     * @return mixed|null
     */
    public function getPlaceholder() {
        return $this->getDomAttr('placeholder');
    }

    /**
     * 获取Tpl文件名
     * @return mixed
     */
    private function getTpl() {
        return str_replace( [__NAMESPACE__, "/", "\\"], '', $this->type );
    }

    /**
     * 执行模板
     * @throws Exception
     */
    public function fetch() {
        self::$view->assign( 'domAttrs', $this->domAttrs );
        return self::$view->fetch(DS . $this->tpl);
    }

    /**
     * tostring 方法
     */
    public function __toString()
    {
        return $this->render();
    }

    /**
     * 抛出一个异常
     * @param string    $msg    异常信息
     * @param int       $code   异常编码
     * @throws Exception
     */
    protected function throwException ( $msg, $code = CatchException::WidgetErrorException ) {
        throw new Exception($msg, $code);
    }


}